package cn.yuxiaoyuan.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import cn.yuxiaoyuan.constants.RedisCacheConstants;
import cn.yuxiaoyuan.domain.DistanceResult;
import cn.yuxiaoyuan.domain.GeoSearchResult;
import cn.yuxiaoyuan.feign.RuleFeignApi;
import cn.yuxiaoyuan.pojo.BaseData;
import cn.yuxiaoyuan.pojo.DistanceDto;
import cn.yuxiaoyuan.pojo.domain.Order;
import cn.yuxiaoyuan.mapper.OrderMapper;
import cn.yuxiaoyuan.pojo.domain.OrderBill;
import cn.yuxiaoyuan.pojo.ro.CreateOrderRo;
import cn.yuxiaoyuan.result.JSONResult;
import cn.yuxiaoyuan.service.IOrderBillService;
import cn.yuxiaoyuan.service.IOrderService;
import cn.yuxiaoyuan.template.MapTemplate;
import cn.yuxiaoyuan.util.RedisUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.aspectj.weaver.ast.Or;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import cn.yuxiaoyuan.constants.Constants;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author whale
 * @since 2025-06-28
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private RuleFeignApi ruleFeignApi;
    @Autowired
    private MapTemplate mapTemplate;
    @Autowired
    private IOrderBillService orderBillService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Override
    @Transactional
    public JSONResult createOrder(CreateOrderRo ro) {
        Date date = new Date();
        //开始就应该给去数据库查询 当前用户 的订单是什么状态  待接单 已经接单 退出   我们必须保证一次只能有一个订单不能重复创建
        Order order = super.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getCustomerId, StpUtil.getLoginIdAsLong())
                .in(Order::getStatus,
                        Arrays.asList(Constants.Order.STATUS_WAIT_ACCEPT
                                , Constants.Order.STATUS_ACCEPT
                                , Constants.Order.STATUS_DRIVER_ARRIVE
                                , Constants.Order.STATUS_START_DRIVE)
                )
        );

        if(order == null){
            //创建订单
            BigDecimal distanceKm = buildOrder(ro, date, order);
            //创建账单
            buildOrderBill(date, order, distanceKm);
        }else {
            return JSONResult.error("订单正在执行中");
        }

        //将乘客下的单推送给司机   MQ进行推送
        //找附近的司机
        List<GeoSearchResult> geoSearchResults = redisUtil.searchGeo(RedisCacheConstants.REDIS_GEO_KEY,
                Double.valueOf(ro.getStartPlaceLongitude()),
                Double.valueOf(ro.getStartPlaceLatitude()),
                5, 5L);
        if(geoSearchResults.isEmpty()){
            return JSONResult.builder().message("请等待司机接单").code(900).data(order.getOrderNo()).success(false).build();
        }
        //推送给司机
        for (GeoSearchResult geoSearchResult : geoSearchResults) {
            //司机的id
            Long driverId = Long.valueOf(geoSearchResult.getMember().toString());
            //司机的ID作为消息的过滤
            String tags = "tags-order-"+driverId;
            SendResult sendResult = rocketMQTemplate.syncSend(Constants.MQ.TOPIC_ORDER2DRIVER + ":" + tags,
                    MessageBuilder.withPayload(order).build());
            System.out.println(sendResult);
        }

        return JSONResult.builder().message("创建订单成功").data(order.getOrderNo()).build();
    }

    private BigDecimal buildOrder(CreateOrderRo ro, Date date, Order order) {
        order.setId(IdUtil.createSnowflake(1L, 1L).nextId());
        order.setOrderNo(IdUtil.createSnowflake(1L, 1L).nextIdStr());
        order.setCustomerId(StpUtil.getLoginIdAsLong());

        order.setStartPlace(ro.getStartPlace());
        order.setEndPlace(ro.getEndPlace());
        order.setFavourAmount(new BigDecimal(0));
        order.setCreateTime(date);
        order.setCarPlate(ro.getCarPlate());
        order.setCarType(ro.getCarType());
        order.setStatus(Constants.Order.STATUS_WAIT_ACCEPT);

        order.setStartPlaceLongitude(ro.getStartPlaceLongitude());
        order.setStartPlaceLatitude(ro.getStartPlaceLatitude());
        order.setEndPlaceLongitude(ro.getEndPlaceLongitude());
        order.setEndPlaceLatiude(ro.getEndPlaceLatitude());

        order.setCustomerName(StpUtil.getExtra("username").toString());
        order.setCustomerPhone(StpUtil.getExtra("phone").toString());
        order.setCustomerPhoto(StpUtil.getExtra("avatar").toString());

        //通过地图计算出来的 距离 和 分钟数
        DistanceResult distanceResult = mapTemplate.distanceMeasure("driving",
                Double.valueOf(ro.getStartPlaceLatitude()),
                Double.valueOf(ro.getStartPlaceLongitude()),
                Double.valueOf(ro.getEndPlaceLatitude()),
                Double.valueOf(ro.getEndPlaceLongitude()));
        BigDecimal distanceKm = new BigDecimal(distanceResult.getDistanceKm());
        order.setExpectsMileage(distanceKm);
        order.setExpectMinutes(distanceResult.getDurationMin());

        DistanceDto distanceDto = new DistanceDto();
        BeanUtils.copyProperties(distanceResult,distanceDto);
        distanceDto.setCreateTime(date);
        BigDecimal priceData = (BigDecimal)ruleFeignApi.price(distanceDto).getData();
        order.setExpectsOrderAmount(priceData);
        super.save(order);
        return distanceKm;
    }

    private void buildOrderBill(Date date, Order order, BigDecimal distanceKm) {
        JSONResult baseRule = ruleFeignApi.getBaseRule();
        BaseData data = JSON.parseObject(baseRule.getData().toString(), BaseData.class);

        OrderBill orderBill = new OrderBill();
        orderBill.setId(IdUtil.createSnowflake(1L, 1L).nextId());
        orderBill.setOrderId(order.getId());
        orderBill.setBaseMileage(data.getBaseMileage());
        orderBill.setBaseMileageAmount(data.getAmount());
        orderBill.setExceedBaseMileage(data.getExceedEveryKmAmount());
        if(distanceKm.intValue() > data.getBaseMileage().intValue()){
            int round = distanceKm.intValue() - data.getBaseMileage().intValue();
            orderBill.setExceedBaseMileage(new BigDecimal(round));
            orderBill.setExceedBaseMileageAmount(data.getExceedEveryKmAmount().multiply(new BigDecimal(round)));
        }else {
            orderBill.setExceedBaseMileage(new BigDecimal(0));
            orderBill.setExceedBaseMileageAmount(new BigDecimal(0));
        }
        orderBill.setMileageAmount(order.getExpectsOrderAmount());


        orderBill.setFreeBaseWaitingMinute(data.getFreeBaseWaitingMinute());
        orderBill.setExeceedBaseWaitingEveryKmAmount(data.getExceedEveryMinuteAmount());


        orderBill.setReturnMileage(order.getExpectsMileage());
        orderBill.setFreeBaseReturnMileage(data.getFreeBaseReturnMileage());
        orderBill.setExceedBaseReturnEveryKmAmount(data.getExceedEveryKmReturnAmount());
        if(distanceKm.intValue() - data.getFreeBaseReturnMileage().intValue() > 0){
            int returnKm  = distanceKm.intValue() - data.getFreeBaseReturnMileage().intValue();
            orderBill.setExceedFreeBaseReturnMileage(new BigDecimal(returnKm));
            orderBill.setReturnAmont(data.getExceedEveryKmReturnAmount().multiply(new BigDecimal(returnKm)));
        }else {
            orderBill.setExceedFreeBaseReturnMileage(new BigDecimal(0));
        }
        orderBill.setOrderNo(order.getOrderNo());
        orderBill.setCreateTime(date);
        orderBillService.save(orderBill);
    }


}
